package mysql

import (
	"fmt"
	"log"
	"os"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"

	"mxshop_srvs/user_srv/model"
	"mxshop_srvs/user_srv/setting"
)

// Gorm defines a gorm dao.
type Gorm struct {
	db *gorm.DB
}

// NewGorm creates a gorm dao.
func NewGorm(db *gorm.DB) *Gorm {
	return &Gorm{
		db: db,
	}
}

// GetUserCount get the number of users.
func (g *Gorm) GetUserCount() (int64, error) {
	var count int64
	result := g.db.Model(&model.User{}).Count(&count)
	if err := result.Error; err != nil {
		return count, err
	}
	return count, nil
}

// GetUserList get users by page number.
func (g *Gorm) GetUserList(page, pageSize int) []model.User {
	var users []model.User
	g.db.Scopes(Paginate(page, pageSize)).Find(&users)
	return users
}

// GetUserByMobile get user by mobile.
func (g *Gorm) GetUserByMobile(mobile string) (user model.User, err error) {
	result := g.db.Where(&model.User{Mobile: mobile}).First(&user)
	if err := result.Error; err != nil {
		return model.User{}, err
	}
	return user, nil
}

// GetUserByID get user by id.
func (g *Gorm) GetUserByID(ID int32) (user model.User, err error) {
	result := g.db.First(&user, ID)
	if err := result.Error; err != nil {
		return model.User{}, err
	}
	return user, nil
}

// CreateUser creates a user.
func (g *Gorm) CreateUser(user model.User) error {
	result := g.db.Create(&user)
	if err := result.Error; err != nil {
		return err
	}
	return nil
}

// UpdateUser updates a user.
func (g *Gorm) UpdateUser(user model.User) error {
	result := g.db.Save(&user) // 使用Save()方法,会保存所有的字段,即使字段是零值
	if result.Error != nil {
		return result.Error
	}
	return nil
}

func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if page == 0 {
			page = 1
		}

		switch {
		case pageSize > 100:
			pageSize = 100
		case pageSize <= 0:
			pageSize = 10
		}

		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

func Init() (*gorm.DB, error) {
	conf := setting.Conf.MysqlConfig
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		conf.User, conf.Password, conf.Host, conf.Port, conf.Database)

	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold: time.Second, // 慢 SQL 阈值
			LogLevel:      logger.Info, // Log level
			Colorful:      true,        // 禁用彩色打印
		},
	)

	// 全局模式
	var err error
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true,
		},
		Logger: newLogger,
	})
	if err != nil {
		return nil, err
	}
	return db, nil
}
